#!/bin/bash

source ../../lib/shell/common.sh

ALL_SMART_DISK=$(smartctl --scan |grep -v nvme|awk '{print $1}')
LSBLK_DISK=$(lsblk | grep -w disk | grep -vE "NAME|nvme" | awk '{print $1}')


function check_disk_supported_smartctl() {
    # check if there are disks not supported smartctl
    for disk in $LSBLK_DISK;do
        if ! echo "$ALL_SMART_DISK"|grep -wq ${disk};then
            write_messages err "dev: ${disk} does not supported smartctl, pls check."
            test_fail
        else
            write_messages info "dev ${disk} support smartctl"
        fi
    done
    write_messages info "========all disk support smartctl, check successfully.=========="
}

function check_smartctl_enabled_for_all_disk() {
    # for each disk, check smartctl enabled.
    for disk in $LSBLK_DISK;do
        if smartctl -i /dev/${disk} |grep -wq "SMART support is: Enabled";then
            write_messages info "dev ${disk} SMART support is enabled."
        else
            write_messages warn "dev ${disk} SMART support is not enabled, and enable it now."
            smartctl -s on /dev/${disk}
            if [ $? -ne 0 ]; then
                write_messages err "dev ${disk} SMART support enable failed."
                test_fail
            fi
        fi
    done
    write_messages info "=========all disk smartctl suopport is enabled, check successfully.==========="
}

function wait_specified_mins() {
    local test_mins=$1
    local b=''
    local i=0
    local progress_percentage=0
    local rum_times=$(expr $test_mins \* 60) 
    for ((i=1; i<=$rum_times; i++));do
        if [ $i -lt 99 ];then
            printf "\033[5m progress:[%-50s]%d%%\r\033[0m" $b $progress_percentage
        fi
        sleep 1
        i=$(expr 1 + $i)
        progress_percentage=${i}
        if [ $progress_percentage -le 100 ];then
            b=#$b
        fi
    done
    if [ $test_mins -le 1 ];then
        for ((i=$progress_percentage; i<100; i++));do
            printf "\033[5m progress:[%-50s]%d%%\r\033[0m" $b $i
            sleep 1
            b=#$b
        done
        printf "progress:[%-50s]%d%%\r" $b 100
    else
        sleep 10
        printf "progress:[%-50s]%d%%\r" $b 100
    fi
    echo ""
}

function exec_smartclt_test_for_one_disk() {
    smartctl -t short /dev/$1
    if [ $? -ne 0 ];then
        write_messages err "dev $1 short self-test cmd run failed."
        test_fail
    fi
}

function check_test_result_for_one_disk() {
    local disk=$1
    if ! smartctl -l selftest /dev/${disk}|grep "Short offline"|grep -wq "Completed without error";then
        write_messages err "dev $disk short self-test result failed, ret: `smartctl -l selftest /dev/${disk}|grep "Short offline"`"
        test_fail
    fi
}

function exec_smartclt_test() {
    # for each disk, exec short smartctl test.
    local test_time_in_mins
    for disk in $LSBLK_DISK;do
        if smartctl -x /dev/${disk} |grep "Short self-test routine" -A1 |grep -wq "minutes";then
            test_time_in_mins=$(smartctl -x /dev/${disk} | grep "Short self-test routine" -A1 |grep minutes |tr -cd "[0-9]")
            if [[ $test_time_in_mins == *[!0-9]* ]];then
                write_messages err "dev ${disk} short self-test routine recommended polling time get failed."
                test_fail
            else
                write_messages info "====dev ${disk} short self-test routine recommended polling time: ${test_time_in_mins} minutes.===="
                exec_smartclt_test_for_one_disk "${disk}"
                wait_specified_mins "$test_time_in_mins"
                check_test_result_for_one_disk "${disk}"
                write_messages info "====dev $disk short self-test result successfully.===="
            fi
        else
            write_messages err "dev ${disk} short self-test routine recommended polling time unit get failed."
            test_fail
        fi
    done
}

function check_attr_val_with_type_old_age() {
    local attr_thresh
    local attr_val
    local attr_worst
    local attr_name
    local disk=$1

    while read attr_info; do
        attr_val=$(echo "${attr_info}" | awk '{print $4}')
        attr_thresh=$(echo "${attr_info}" | awk '{print $6}')
        attr_worst=$(echo "${attr_info}" | awk '{print $5}')
        attr_name=$(echo "${attr_info}" | awk '{print $2}')
        if [ $attr_val -le $attr_thresh ] || [ $attr_worst -le $attr_thresh ];then
            write_messages err "dev ${disk} attr ${attr_name} is not healthy, val: $attr_val, worst: $attr_worst, thresh: $attr_thresh."
            test_fail
        else
            write_messages info "dev ${disk} attr: ${attr_name} is healthy, val: $attr_val, worst: $attr_worst, thresh: $attr_thresh."
        fi
    done << EOF
    `smartctl -A /dev/${disk} | grep "Old_age"`
EOF
}

function check_all_disk_attr_val_with_type_old_age() {
    for disk in $LSBLK_DISK;do
        write_messages info "====Disk: ${disk} attribute health value detection.===="
        check_attr_val_with_type_old_age "${disk}"
        write_messages info "====Disk: ${disk} attribute health value detection successfully.===="
    done
}

# # # # # # # # # # # # # # main # # # # # # # # # # # # # #
write_messages info "=========system disk smartctl test============="
check_disk_supported_smartctl
check_smartctl_enabled_for_all_disk
check_all_disk_attr_val_with_type_old_age

exec_smartclt_test
test_pass
